﻿using Decal.Adapter;
using System;
using System.Text;

namespace SixthSense
{
    public partial class PluginCore : PluginBase
    {
        private void initEchoFilter()
        {
            Core.EchoFilter.ServerDispatch +=new EventHandler<NetworkMessageEventArgs>(EchoFilter_ServerDispatch);
        }

        void EchoFilter_ServerDispatch(object sender, NetworkMessageEventArgs e)
        {
            switch (e.Message.Type)
            {
                //Object Destroyed
                case 0x0024:
                    {
                        int objectID;
                        try { objectID = e.Message.Value<int>("object"); }
                        catch (ArgumentOutOfRangeException) { return; }
                        WriteToChat("ServerDispatch: Object Destroyed " + objectID);
                        RemoveItem(objectID);
                    }
                    break;

                case 0xF74A:
                case 0xF747:
                    {
                        int objectID;
                        try { objectID = e.Message.Value<int>("object"); }
                        catch (ArgumentOutOfRangeException) { return; }
                        RemoveItem(objectID);
                    }
                    break;

                case 0xF7DE: // chat message
                case 0x02CD:
                case 0xF745:
                    {
                        bool bFound = false;

                        MessageStruct msPosition;
                        ObjectInfo oiItem = new ObjectInfo();
                        AlertInfo aiItem = new AlertInfo();

                        int objectID = e.Message.Value<int>("object");
                        MessageStruct msGame = e.Message.Struct("game");
                        MessageStruct msPhysics = e.Message.Struct("physics");
                        oiItem.Name = msGame.Value<string>("name");

                        aiItem.Name = oiItem.Name;

                        //WriteToChat("ServerDispatch: 0xF745 " + aiItem.Name);

                        oiItem.Icon = msGame.Value<int>("icon");

                        if ((_Config.CurrentOptions.IgnoreHooks) && (oiItem.Icon == 0x20C0))
                        {
                            WriteToChat("ServerDispatch: 0xF745 - Ignore Hooks: " + aiItem.Name);
                            break;
                        }

                        bool bAlreadyPresent = false;

                        ObjectInfo FoundItem = new ObjectInfo();

                        FoundItem = _Items.FindById(objectID);
                        if (FoundItem != null)
                        {
                            WriteToChat("Tracked Item found: " + FoundItem.Name);
                            bAlreadyPresent = true;
                            bFound = true;
                        }

                        if (!bAlreadyPresent)
                        {
                            FoundItem = _Monsters.FindById(objectID);
                            if (FoundItem != null)
                            {
                                WriteToChat("Tracked Monster found: " + FoundItem.Name);
                                bAlreadyPresent = true;
                                bFound = true;
                            }
                        }

                        if (!bAlreadyPresent)
                        {
                            FoundItem = _Specials.FindById(objectID);
                            if (FoundItem != null)
                            {
                                WriteToChat("Tracked Special found: " + FoundItem.Name);
                                bAlreadyPresent = true;
                                bFound = true;
                            }
                        }

                        if (bAlreadyPresent)
                        {
                            msPosition = msPhysics.Struct("position");
                            oiItem.Landblock = msPosition.Value<int>("landcell");
                            oiItem.xOffset = msPosition.Value<int>("x");
                            oiItem.yOffset = msPosition.Value<int>("y");

                            UpdateItemLocation(oiItem);
                        }

                        // test if this item is wielded, and if so, were done
                        int wielder = msGame.Value<int>("equipper");

                        if (wielder > 0)
                        {
                            //WriteToChat("ServerDispatch: 0xF745 - Item Wielded " + oiItem.Name + " (" + wielder + ")");
                            break;
                        }

                        if ((objectID == PlayerObject.ID) && (PlayerObject.Name == null))
                        {
                            WriteToChat("Setting PlayerObject.Name to " + oiItem.Name);
                            PlayerObject.Name = oiItem.Name;

                            _Config.Personalize(oiItem.Name);
                            break;
                        }

                        if ((oiItem.Name == "Pack") || (oiItem.Name == "Sack"))
                        {
                            // try to foil the thieves
                            WriteToChat("Found a container: " + oiItem.Name);
                            break;
                        }

                        // FindByName will check for enabled, and substrings plus excludes
                        // Original code had to do all that here
                        AlertInfo aiFound = _Config.CurrentProfile.Alerts.FindByName(aiItem.Name);

                        if (aiFound != null)
                        {
                            aiItem = aiFound.Copy();
                            bFound = true;

                            WriteToChat("Found item by name: " + aiFound.Name);
                        }
                        else
                        {
                            // didnt find it by name
                            if (_Config.CurrentOptions.TrackPortals)
                            {
                                if ((oiItem.Icon == 0x106B) && (!oiItem.Name.StartsWith("Destroyed")))
                                {
                                    WriteToChat("Tracking portals. Found one: " + oiItem.Name);
                                    oiItem.Type = "loot";
                                    aiItem.Sound = "portal.wav";
                                    bFound = true;
                                }
                            }

                            if (_Config.CurrentOptions.TrackValue)
                            {
                                oiItem.Value = msGame.Value<int>("value");

                                if (oiItem.Value >= _Config.CurrentOptions.MinValue)
                                {
                                    if (_Config.CurrentOptions.TrackRatio)
                                    {
                                        // if the value is over our threshold, do a stealth-id on it.
                                        WriteToChat("Adding item to Value queue: " + oiItem.Name);
                                        _ValueQueue.Add(oiItem);
                                        Core.IDQueue.AddToQueue(objectID);
                                    }
                                    else
                                    {
                                        WriteToChat("Identified item to track for Value");
                                        oiItem.Type = "loot";
                                        aiItem.Sound = "value.wav";
                                        bFound = true;
                                    }
                                }
                            }

                            // test for material tracking
                            int material = msGame.Value<int>("material");

                            MaterialInfo mat = _Config.CurrentProfile.Materials.FindById(material);

                            if (mat != null)
                            {
                                // can see the material here, but not the workmanship.
                                // anything over 0 means were looking for it
                                if (mat.Workmanship > 0)
                                {
                                    // if the material is one we're looking for, but we only
                                    // want to see X workmanship, stealth-id time.
                                    WriteToChat("Adding item to Workmanship Queue: " + oiItem.ID);

                                    _WorkmanshipQueue.Add(oiItem);
                                    Core.IDQueue.AddToQueue(objectID);
                                }
                            }
                        }

                        if (bFound == true)
                        {
                            WriteToChat("Preparing to add item: " + oiItem.Name);

                            msPosition = msPhysics.Struct("position");
                            oiItem.Landblock = msPosition.Value<int>("landcell");
                            oiItem.xOffset = msPosition.Value<float>("x");
                            oiItem.yOffset = msPosition.Value<float>("y");

                            PlaySound(aiItem.Sound);
                            AddItem(oiItem);
                            UpdateItemLocation(oiItem);

                            if (_Config.CurrentOptions.Clipboard)
                            {
                                // TODO implement clipboard
                            }
                        }
                    }
                    break;

                case 0xF748: // object moved
                    {
                        int objectID = e.Message.Value<int>("object");
                        MessageStruct msPosition = e.Message.Struct("position");
                        int Landblock = msPosition.Value<int>("landcell");
                        int xOffset = msPosition.Value<int>("x");
                        int yOffset = msPosition.Value<int>("y");

                        if (objectID == PlayerObject.ID)
                        {
                            PlayerObject.Landblock = Landblock;
                            PlayerObject.xOffset = xOffset;
                            PlayerObject.yOffset = yOffset;
                            
                            UpdateItemLocations();
                        }

                        ObjectInfo obj;
                        obj = _Items.FindById(objectID);
                        if (obj == null)
                        {
                            obj = _Monsters.FindById(objectID);
                            if (obj == null)
                            {
                                obj = _Specials.FindById(objectID);
                            }
                        }

                        if (obj != null)
                        {
                            obj.Landblock = Landblock;
                            obj.xOffset = xOffset;
                            obj.yOffset = yOffset;
                        }

                        UpdateItemLocation(obj);
                    }
                    break;

                case 0xf7B0: // General game event
                    {
                        //WriteToChat("EchoFilter_ServerDispatch 0xF7B0");

                        if (PlayerObject.ID == 0)
                        {
                            PlayerObject.ID = e.Message.Value<int>("character");
                            //WriteToChat("Updating PlayerObject.ID: " + PlayerObject.ID);
                        }

                        int Event = e.Message.Value<int>("event");

                        if (Event == 0x0022)
                        {
                            int itemId = e.Message.Value<int>("item");
                            RemoveItem(itemId);
                            WriteToChat("Event 0x0022 - Removed " + itemId);
                        }
                        else if( Event == 0x0013)
                        {
                            //WriteToChat("Event 0x0013 - PlayerObject.Name: (" + PlayerObject.Name + ")");
                            if (PlayerObject.Name == null)
                            {
                                MessageStruct msProperties = e.Message.Struct("properties");
                                MessageStruct msStrings = msProperties.Struct("strings");

                                if (msStrings.Count > 0)
                                {
                                    MessageStruct msString = msStrings.Struct(0);
                                    PlayerObject.Name = msString.Value<string>("value");

                                    WriteToChat("Tracking Player: " + PlayerObject.Name + " (" + PlayerObject.ID + ")");
                                    _Config.Personalize(PlayerObject.Name);
                                }
                            }
                        }
                        else if (Event == 0x00C9) // onAssessItem
                        {
                            AlertInfo alert = new AlertInfo();

                            int objectID = e.Message.Value<int>("object");
                            WriteToChat("Event 0x00C9 - onAssessItem, ID: " + objectID);

                            ObjectInfo FoundItem  = _ValueQueue.FindById(objectID);

                            if(FoundItem != null)
                            {
                                WriteToChat("Found object in the Value queue: " + FoundItem.Name);
                                _ValueQueue.Remove(FoundItem);
                                MessageStruct msDwords = e.Message.Struct("dwords");

                                if (msDwords.Count > 0)
                                {
                                    int index;
                                    for (index = 0; index < msDwords.Count ; index++)
                                    {
                                        MessageStruct msDword = msDwords.Struct(index);
                                        int Key = msDword.Value<int>("key");

                                        if (Key == 5)
                                        {
                                            long Burden = msDword.Value<long>("value");

                                            if (Burden < 1)
                                            {
                                                Burden = 1;
                                            }

                                            int Ratio = (int)(FoundItem.Value / Burden);

                                            if (Ratio > _Config.CurrentOptions.Ratio)
                                            {
                                                alert.Sound = "value.wav";
                                                FoundItem.Text = "Value " + FoundItem.Value;
                                            }
                                            break;
                                        }
                                    }
                                }
                            }

                            if (alert.Sound != "")
                            {
                                FoundItem = _WorkmanshipQueue.FindById(objectID);

                                if (FoundItem != null)
                                {
                                    WriteToChat("Found object in the Workmanship queue: " + FoundItem.Name);
                                    _WorkmanshipQueue.Remove(FoundItem);
                                    MessageStruct msDwords = e.Message.Struct("dwords");

                                    if (msDwords.Count > 0)
                                    {
                                        float Work = 1;
                                        float Divisor = 1;
                                        int index;
                                        for (index = 0; index < msDwords.Count; index++)
                                        {
                                            MessageStruct msDword = msDwords.Struct(index);
                                            int Key = msDword.Value<int>("key");

                                            if (Key == 0x69) // Work
                                            {
                                                Work = msDword.Value<float>("value");

                                                if (Work < 1)
                                                {
                                                    Work = 1;
                                                }
                                            }
                                            else if (Key == 0xaa)
                                            {
                                                Divisor = msDword.Value<float>("value");
                                            }

                                            if (Divisor < 1)
                                            {
                                                Divisor = 1;
                                            }

                                            if ((Work / Divisor) >= (float)FoundItem.Material.Workmanship)
                                            {
                                                alert.Sound = "alert2.wav";
                                                FoundItem.Text = "Material " + FoundItem.Material.Name;
                                            }
                                        }
                                    }
                                }
                            }
                            if (alert.Sound != "")
                            {
                                FoundItem.Type = "item";
                                AddItem(FoundItem);
                                PlaySound(alert.Sound);
                                UpdateItemLocation(FoundItem);
                            }
                        }
                    }
                    break;

                default:
                    {
                        //WriteToChat("EchoFilter_ServerDispatch " + e.Message.Type);
                    }
                    break;
            }
        }

        private void destroyEchoFilter()
        {
            Core.EchoFilter.ServerDispatch -= new EventHandler<NetworkMessageEventArgs>(EchoFilter_ServerDispatch);
        }
    }
}